<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>验证</title>
    <style type="text/css">
        body {
            margin: 50px 0;
            text-align: center;
            font-family: "PingFangSC-Regular", "Open Sans", Arial, "Hiragino Sans GB", "Microsoft YaHei", "STHeiti", "WenQuanYi Micro Hei", SimSun, sans-serif;
        }

        .inp {
            border: 1px solid #cccccc;
            border-radius: 2px;
            padding: 0 10px;
            width: 320px;
            height: 40px;
            font-size: 18px;
        }

        .btn {
            display: inline-block;
            box-sizing: border-box;
            border: 1px solid #cccccc;
            border-radius: 2px;
            width: 100px;
            height: 40px;
            line-height: 40px;
            font-size: 16px;
            color: #666;
            cursor: pointer;
            background: white linear-gradient(180deg, #ffffff 0%, #f3f3f3 100%);
        }

        .btn:hover {
            background: white linear-gradient(0deg, #ffffff 0%, #f3f3f3 100%)
        }

        #captcha {
            width: 300px;
            display: inline-block;
        }

        label {
            vertical-align: top;
            display: inline-block;
            width: 120px;
            text-align: right;
        }

        #text {
            height: 42px;
            width: 298px;
            text-align: center;
            border-radius: 2px;
            background-color: #F3F3F3;
            color: #BBBBBB;
            font-size: 14px;
            letter-spacing: 0.1px;
            line-height: 42px;
        }

        #wait {
            display: none;
            height: 42px;
            width: 298px;
            text-align: center;
            border-radius: 2px;
            background-color: #F3F3F3;
        }

        .loading {
            margin: auto;
            width: 70px;
            height: 20px;
        }

        .loading-dot {
            float: left;
            width: 8px;
            height: 8px;
            margin: 18px 4px;
            background: #ccc;

            -webkit-border-radius: 50%;
            -moz-border-radius: 50%;
            border-radius: 50%;

            opacity: 0;

            -webkit-box-shadow: 0 0 2px black;
            -moz-box-shadow: 0 0 2px black;
            -ms-box-shadow: 0 0 2px black;
            -o-box-shadow: 0 0 2px black;
            box-shadow: 0 0 2px black;

            -webkit-animation: loadingFade 1s infinite;
            -moz-animation: loadingFade 1s infinite;
            animation: loadingFade 1s infinite;
        }

        .loading-dot:nth-child(1) {
            -webkit-animation-delay: 0s;
            -moz-animation-delay: 0s;
            animation-delay: 0s;
        }

        .loading-dot:nth-child(2) {
            -webkit-animation-delay: 0.1s;
            -moz-animation-delay: 0.1s;
            animation-delay: 0.1s;
        }

        .loading-dot:nth-child(3) {
            -webkit-animation-delay: 0.2s;
            -moz-animation-delay: 0.2s;
            animation-delay: 0.2s;
        }

        .loading-dot:nth-child(4) {
            -webkit-animation-delay: 0.3s;
            -moz-animation-delay: 0.3s;
            animation-delay: 0.3s;
        }

        @-webkit-keyframes loadingFade {
            0% {
                opacity: 0;
            }

            50% {
                opacity: 0.8;
            }

            100% {
                opacity: 0;
            }
        }

        @-moz-keyframes loadingFade {
            0% {
                opacity: 0;
            }

            50% {
                opacity: 0.8;
            }

            100% {
                opacity: 0;
            }
        }

        @keyframes loadingFade {
            0% {
                opacity: 0;
            }

            50% {
                opacity: 0.8;
            }

            100% {
                opacity: 0;
            }
        }
    </style>
</head>

<body>
    <h1 align="center">
        请完成验证码
    </h1>
    <div>
        <div id="captcha">
            <div id="wait" class="show">
                <div class="loading">
                    <div class="loading-dot"></div>
                    <div class="loading-dot"></div>
                    <div class="loading-dot"></div>
                    <div class="loading-dot"></div>
                </div>
            </div>
        </div>
    </div>
    <br>
    <button id="done">完成！</button>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <script>
        "v0.4.8 Geetest Inc.";

        (function (window) {
            "use strict";
            if (typeof window === 'undefined') {
                throw new Error('Geetest requires browser environment');
            }

            var document = window.document;
            var Math = window.Math;
            var head = document.getElementsByTagName("head")[0];

            function _Object(obj) {
                this._obj = obj;
            }

            _Object.prototype = {
                _each: function (process) {
                    var _obj = this._obj;
                    for (var k in _obj) {
                        if (_obj.hasOwnProperty(k)) {
                            process(k, _obj[k]);
                        }
                    }
                    return this;
                }
            };

            function Config(config) {
                var self = this;
                new _Object(config)._each(function (key, value) {
                    self[key] = value;
                });
            }

            Config.prototype = {
                api_server: 'api.geetest.com',
                protocol: 'http://',
                typePath: '/gettype.php',
                fallback_config: {
                    slide: {
                        static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
                        type: 'slide',
                        slide: '/static/js/geetest.0.0.0.js'
                    },
                    fullpage: {
                        static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
                        type: 'fullpage',
                        fullpage: '/static/js/fullpage.0.0.0.js'
                    }
                },
                _get_fallback_config: function () {
                    var self = this;
                    if (isString(self.type)) {
                        return self.fallback_config[self.type];
                    } else if (self.new_captcha) {
                        return self.fallback_config.fullpage;
                    } else {
                        return self.fallback_config.slide;
                    }
                },
                _extend: function (obj) {
                    var self = this;
                    new _Object(obj)._each(function (key, value) {
                        self[key] = value;
                    })
                }
            };
            var isNumber = function (value) {
                return (typeof value === 'number');
            };
            var isString = function (value) {
                return (typeof value === 'string');
            };
            var isBoolean = function (value) {
                return (typeof value === 'boolean');
            };
            var isObject = function (value) {
                return (typeof value === 'object' && value !== null);
            };
            var isFunction = function (value) {
                return (typeof value === 'function');
            };
            var MOBILE = /Mobi/i.test(navigator.userAgent);
            var pt = MOBILE ? 3 : 0;

            var callbacks = {};
            var status = {};

            var nowDate = function () {
                var date = new Date();
                var year = date.getFullYear();
                var month = date.getMonth() + 1;
                var day = date.getDate();
                var hours = date.getHours();
                var minutes = date.getMinutes();
                var seconds = date.getSeconds();

                if (month >= 1 && month <= 9) {
                    month = '0' + month;
                }
                if (day >= 0 && day <= 9) {
                    day = '0' + day;
                }
                if (hours >= 0 && hours <= 9) {
                    hours = '0' + hours;
                }
                if (minutes >= 0 && minutes <= 9) {
                    minutes = '0' + minutes;
                }
                if (seconds >= 0 && seconds <= 9) {
                    seconds = '0' + seconds;
                }
                var currentdate = year + '-' + month + '-' + day + " " + hours + ":" + minutes + ":" + seconds;
                return currentdate;
            }

            var random = function () {
                return parseInt(Math.random() * 10000) + (new Date()).valueOf();
            };

            var loadScript = function (url, cb) {
                var script = document.createElement("script");
                script.charset = "UTF-8";
                script.async = true;

                // 对geetest的静态资源添加 crossOrigin
                if (/static\.geetest\.com/g.test(url)) {
                    script.crossOrigin = "anonymous";
                }

                script.onerror = function () {
                    cb(true);
                };
                var loaded = false;
                script.onload = script.onreadystatechange = function () {
                    if (!loaded &&
                        (!script.readyState ||
                            "loaded" === script.readyState ||
                            "complete" === script.readyState)) {

                        loaded = true;
                        setTimeout(function () {
                            cb(false);
                        }, 0);
                    }
                };
                script.src = url;
                head.appendChild(script);
            };

            var normalizeDomain = function (domain) {
                // special domain: uems.sysu.edu.cn/jwxt/geetest/
                // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn
                return domain.replace(/^https?:\/\/|\/$/g, ''); // uems.sysu.edu.cn/jwxt/geetest
            };
            var normalizePath = function (path) {
                path = path.replace(/\/+/g, '/');
                if (path.indexOf('/') !== 0) {
                    path = '/' + path;
                }
                return path;
            };
            var normalizeQuery = function (query) {
                if (!query) {
                    return '';
                }
                var q = '?';
                new _Object(query)._each(function (key, value) {
                    if (isString(value) || isNumber(value) || isBoolean(value)) {
                        q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
                    }
                });
                if (q === '?') {
                    q = '';
                }
                return q.replace(/&$/, '');
            };
            var makeURL = function (protocol, domain, path, query) {
                domain = normalizeDomain(domain);

                var url = normalizePath(path) + normalizeQuery(query);
                if (domain) {
                    url = protocol + domain + url;
                }

                return url;
            };

            var load = function (config, send, protocol, domains, path, query, cb) {
                var tryRequest = function (at) {

                    var url = makeURL(protocol, domains[at], path, query);
                    loadScript(url, function (err) {
                        if (err) {
                            if (at >= domains.length - 1) {
                                cb(true);
                                // report gettype error
                                if (send) {
                                    config.error_code = 508;
                                    var url = protocol + domains[at] + path;
                                    reportError(config, url);
                                }
                            } else {
                                tryRequest(at + 1);
                            }
                        } else {
                            cb(false);
                        }
                    });
                };
                tryRequest(0);
            };


            var jsonp = function (domains, path, config, callback) {
                if (isObject(config.getLib)) {
                    config._extend(config.getLib);
                    callback(config);
                    return;
                }
                if (config.offline) {
                    callback(config._get_fallback_config());
                    return;
                }

                var cb = "geetest_" + random();
                window[cb] = function (data) {
                    if (data.status == 'success') {
                        callback(data.data);
                    } else if (!data.status) {
                        callback(data);
                    } else {
                        callback(config._get_fallback_config());
                    }
                    window[cb] = undefined;
                    try {
                        delete window[cb];
                    } catch (e) {
                    }
                };
                load(config, true, config.protocol, domains, path, {
                    gt: config.gt,
                    callback: cb
                }, function (err) {
                    if (err) {
                        callback(config._get_fallback_config());
                    }
                });
            };

            var reportError = function (config, url) {
                load(config, false, config.protocol, ['monitor.geetest.com'], '/monitor/send', {
                    time: nowDate(),
                    captcha_id: config.gt,
                    challenge: config.challenge,
                    pt: pt,
                    exception_url: url,
                    error_code: config.error_code
                }, function (err) { })
            }

            var throwError = function (errorType, config) {
                var errors = {
                    networkError: '网络错误',
                    gtTypeError: 'gt字段不是字符串类型'
                };
                if (typeof config.onError === 'function') {
                    config.onError(errors[errorType]);
                } else {
                    throw new Error(errors[errorType]);
                }
            };

            var detect = function () {
                return window.Geetest || document.getElementById("gt_lib");
            };

            if (detect()) {
                status.slide = "loaded";
            }

            window.initGeetest = function (userConfig, callback) {

                var config = new Config(userConfig);

                if (userConfig.https) {
                    config.protocol = 'https://';
                } else if (!userConfig.protocol) {
                    config.protocol = window.location.protocol + '//';
                }

                // for KFC
                if (userConfig.gt === '050cffef4ae57b5d5e529fea9540b0d1' ||
                    userConfig.gt === '3bd38408ae4af923ed36e13819b14d42') {
                    config.apiserver = 'yumchina.geetest.com/'; // for old js
                    config.api_server = 'yumchina.geetest.com';
                }

                if (userConfig.gt) {
                    window.GeeGT = userConfig.gt
                }

                if (userConfig.challenge) {
                    window.GeeChallenge = userConfig.challenge
                }

                if (isObject(userConfig.getType)) {
                    config._extend(userConfig.getType);
                }
                jsonp([config.api_server || config.apiserver], config.typePath, config, function (newConfig) {
                    var type = newConfig.type;
                    var init = function () {
                        config._extend(newConfig);
                        callback(new window.Geetest(config));
                    };

                    callbacks[type] = callbacks[type] || [];
                    var s = status[type] || 'init';
                    if (s === 'init') {
                        status[type] = 'loading';

                        callbacks[type].push(init);

                        load(config, true, config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {
                            if (err) {
                                status[type] = 'fail';
                                throwError('networkError', config);
                            } else {
                                status[type] = 'loaded';
                                var cbs = callbacks[type];
                                for (var i = 0, len = cbs.length; i < len; i = i + 1) {
                                    var cb = cbs[i];
                                    if (isFunction(cb)) {
                                        cb();
                                    }
                                }
                                callbacks[type] = [];
                            }
                        });
                    } else if (s === "loaded") {
                        init();
                    } else if (s === "fail") {
                        throwError('networkError', config);
                    } else if (s === "loading") {
                        callbacks[type].push(init);
                    }
                });

            };


        })(window);
    </script>

    <script>
        var handler = function (captchaObj) {
            captchaObj.appendTo('#captcha');
            captchaObj.onReady(function () {
                $("#wait").hide();
            });
            $("#done").click(function () {
                var result = captchaObj.getValidate();
                if (!result) {
                    alert("请完成验证");
                }
                else {
                    var validate = result.geetest_validate;
                    var seccode = result.geetest_seccode;
                    window.location.href = window.location.href + "result/validate=" + validate + "&seccode=" + seccode;
                }
            });
            // 更多前端接口说明请参见：http://docs.geetest.com/install/client/web-front/
        };
        $('#wait').show();
        // 调用 initGeetest 进行初始化
        // 参数1：配置参数
        // 参数2：回调，回调的第一个参数验证码对象，之后可以使用它调用相应的接口
        initGeetest({
            // 以下 4 个配置参数为必须，不能缺少
            gt: { Python_Interface: GT }, // 这里需要替换成 python 获取的 gt
            challenge: { Python_Interface: CHALLENGE }, // 这里需要替换成 python 获取的 challenge
            offline: false, // 表示用户后台检测极验服务器是否宕机
            new_captcha: true, // 用于宕机时表示是新验证码的宕机

            product: "popup", // 产品形式，包括：float，popup
            width: "300px",
            https: true

            // 更多前端配置参数说明请参见：http://docs.geetest.com/install/client/web-front/
        }, handler);
    </script>
</body>

</html>